package com.yjzx.util.common.util.batch;

import com.yjzx.util.common.util.batch.merging.OverviewMerging;
import com.yjzx.util.common.util.batch.mergingLimit.MergingView;
import com.yjzx.util.common.util.batch.mergingLimit.PagingView;
import com.yjzx.util.common.util.collection.EmptyUtils;

import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author yjzx
 * @date 2024/5/27
 * @description 批量处理方法
 */
public class BatchHandleUtils {
    public static <T> int batchMethod(List<T> list, Function<List<T>, Integer> function) {
        return batchMethod(list, function, 1000);
    }

    public static <T> int batchMethod(List<T> list, Function<List<T>, Integer> function, int maxSize) {
        int num = 0;
        maxSize = maxSize <= 10 ? 25 : maxSize;
        int size = list != null ? list.size() : 0;
        if (size > maxSize) {
            for (int i = 0; i < size; i += maxSize) {
                List<T> reports = list.subList(i, Math.min(i + maxSize, size));
                num += function.apply(reports);
            }
        } else if (size != 0) {
            num = function.apply(list);
        }
        return num;
    }

    /**
     * 合并Collection
     *
     * @param collection
     * @param <V>
     * @param <R>
     * @return
     */
    public static <V, R extends Collection<V>> List<V> mergeToList(Collection<R> collection) {
        if (collection != null) {
            return collection.stream().filter(EmptyUtils::isNotEmpty).flatMap(Collection::stream).collect(Collectors.toList());
        }
        return Collections.emptyList();
    }

    public static <V, R extends Collection<V>> Set<V> mergeToSet(Collection<R> collection) {
        if (collection != null) {
            return collection.stream().filter(EmptyUtils::isNotEmpty).flatMap(Collection::stream).collect(Collectors.toSet());
        }
        return Collections.emptySet();
    }

    public static <T, R> List<R> convertList(Collection<T> list, Function<T, R> resultConvert,boolean nullable) {
        if (EmptyUtils.isEmpty(list) || EmptyUtils.isEmpty(resultConvert)) {
            return Collections.emptyList();
        }
        return list.stream()
                .map(resultConvert).filter(x->nullable||x!=null)
                .collect(Collectors.toList());
    }

    /**
     * 转换为result类型(<T> 需继承 ){@link ResultConvert}
     *
     * @param list  需转换的数据
     * @param param 参数
     * @param <T>   数据类型
     * @param <U>   参数类型
     * @param <R>   返回类型
     * @return
     */
    public static <T extends ResultConvert<U, R>, U, R> List<R> toResult(Collection<T> list, U param) {
        return list != null ? list.stream().filter(Objects::nonNull)
                .map(x -> x.toResult(param)).filter(Objects::nonNull)
                .collect(Collectors.toList()) : Collections.emptyList();
    }

    /**
     * 以指定节点获取分割的返回数据(old)
     *
     * @param overview 参数
     * @param <T>      方法运行参数类型
     * @param <U>      节点类型
     * @param <R>      返回值类型
     * @return
     */
    public static <T, U extends Comparable<U>, R> List<R> toDataMerging(OverviewMerging<T, U, R> overview) {
        return overview.toDataMerging();
    }
    /**
     * 以指定节点获取分割的返回数据
     *
     * @param mergingView 参数
     * @param <T>      方法运行参数类型
     * @param <U>      节点类型
     * @param <R>      返回值类型
     * @return
     */
    public static <T, U extends Comparable<U>, R> List<R> toDataMerging(MergingView<T, U, R> mergingView) {
        return mergingView.toDataMerging();
    }
    /**
     * 以多个数据分页结合获取分割的返回数据（不能添加排序）
     *
     * @param mergingView 参数
     * @param <T>      方法运行参数类型
     * @param <U>      节点类型
     * @param <R>      返回值类型
     * @return
     */
    public static <T, U extends Comparable<U>, R> List<R> toDataMerging(PagingView<T, R> mergingView) {
        return mergingView.toDataPaging();
    }
}
